package com.inspur.edp.udt.designtime.manager.generatecomponent;


import com.inspur.edp.bef.component.base.GspComponent;
import com.inspur.edp.bef.component.json.ComponentConstantElement;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.MetadataHeader;
import com.inspur.edp.lcm.metadata.api.entity.MetadataReference;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import com.inspur.edp.udt.designtime.api.exception.UdtModelErrorCodeEnum;
import com.inspur.edp.udt.designtime.api.exception.UdtModelException;
import com.inspur.edp.udt.designtime.api.utils.UdtUtils;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

/**
 * 与元数据交互的工具
 */
public class GspMetadataExchangeUtil {

  private GspMetadataExchangeUtil() {
  }

  public static GspMetadataExchangeUtil getInstance() {
    return new GspMetadataExchangeUtil();
  }

  /**
   * 业务实体编号
   */
  private String privateBizEntityCode;

  private String getBizEntityCode() {
    return privateBizEntityCode;
  }

  private void setBizEntityCode(String value) {
    privateBizEntityCode = value;
  }

  /**
   * 元数据存放路径
   */
  private String privateMetadataPath;

  private String getMetadataPath() {
    return privateMetadataPath;
  }

  private void setMetadataPath(String value) {
    privateMetadataPath = value;
  }

  /**
   * 元数据名称
   */
  private String privateComponentName;

  private String getComponentName() {
    return privateComponentName;
  }

  private void setComponentName(String value) {
    privateComponentName = value;
  }

  /**
   * 是否是新建元数据
   */
  private boolean privateIsNewMetadata;

  private boolean getIsNewMetadata() {
    return privateIsNewMetadata;
  }

  private void setIsNewMetadata(boolean value) {
    privateIsNewMetadata = value;
  }

  private String privateBizObjectID;

  private String getBizObjectID() {
    return privateBizObjectID;
  }

  private void setBizObjectID(String value) {
    privateBizObjectID = value;
  }

  private String privateNameSpace;

  private String getNameSpace() {
    return privateNameSpace;
  }

  private void setNameSpace(String value) {
    privateNameSpace = value;
  }

  /**
   * 创建构件元数据，返回构件元数据ID
   *
   * @param component 构件实体
   * @param path 生成构件元数据的路径
   * @param bizEntityCode 业务实体编号
   * @return 生成的构件元数据名称
   * <see cref="string"/>
   */
  public final String establishGSPMetdadata(GspComponent component, String path,
      String bizEntityCode, String bizObjectID, String nameSpace) {
    this.setIsNewMetadata(true);
    this.setBizEntityCode(bizEntityCode);
    this.setMetadataPath(path);
    this.setBizObjectID(bizObjectID);
    this.setNameSpace(nameSpace);
    //1、构建元数据实体
    GspMetadata metadata = BuildGspMetadataEntity(component);
    //2、生成构件元数据
    return GenerateGspMetadata(metadata);
  }

  /**
   * 更新构件元数据
   *
   * @param component 构件实体
   * @param fullPath 要修改的构件元数据完整路径
   */
  public final void updateGspMetadata(GspComponent component, String fullPath, String bizEntityCode,
      String bizObjectID, String nameSpace) {
    this.setIsNewMetadata(false);
    this.setBizEntityCode(bizEntityCode);
    this.setBizObjectID(bizObjectID);
    this.setNameSpace(nameSpace);
    this.setMetadataPath(UdtUtils.getDirectoryname(fullPath));
    this.setComponentName(UdtUtils.getFileNameWithoutExtension(fullPath));
    //1、构建元数据实体
    GspMetadata metadata = BuildGspMetadataEntity(component);
    UpdateComponentMetadata(metadata, fullPath);
  }

  ///#region 构建构件元数据实体

  /**
   * 创建GspMetadata实体
   *
   * @param component 构件实体
   * @return GspMetadata实体
   */
  private GspMetadata BuildGspMetadataEntity(GspComponent component) {
    GspMetadata metadata = CreateMetadataEntity();

    EvaluateMetadataHeader(component, metadata);
    EvaluateMetadataContent(component, metadata);
    return metadata;
  }

  /**
   * 创建元数据实例
   *
   * @return 实例化的元数据
   * <see cref="GspMetadata"/>
   */
  private GspMetadata CreateMetadataEntity() {
    GspMetadata tempVar = new GspMetadata();
    tempVar.setHeader(new MetadataHeader());
    tempVar.setRefs(new java.util.ArrayList<MetadataReference>());
    GspMetadata metadata = tempVar;
    return metadata;
  }

  /**
   * 为元数据的Header属性赋值
   *
   * @param component 构件实体
   * @param metadata 元数据实体
   */
  private void EvaluateMetadataHeader(GspComponent component, GspMetadata metadata) {
    if (UdtUtils.checkNull(metadata.getHeader().getNameSpace())) {
      metadata.getHeader().setNameSpace(getNameSpace());
    }

//C# TO JAVA CONVERTER TODO TASK: The following line could not be converted:
    metadata.getHeader().setCode(GenerateComponentMetadataName(component, this.getMetadataPath()));
    metadata.getHeader().setName(GenerateComponentMetadataName(component, this.getMetadataPath()));
    metadata.getHeader().setFileName(
        this.getComponentName() + GetCmpMetadataExtendNameByCompType(component.getComponentType()));
    metadata.getHeader().setType(GetCmpMetadataTypeByCompType(component.getComponentType()));

    if (!UdtUtils.checkNull(getBizObjectID())) {
      metadata.getHeader().setBizobjectID(getBizObjectID());
    }

    if (UdtUtils.checkNull(metadata.getHeader().getId()) && UdtUtils
        .checkNull(component.getComponentID())) //新建构件元数据时，需要初始化后获取ID
    {
      MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
      //初始化元数据，为了获取元数据ID
      metadata = metadataService.initializeMetadataEntity(metadata);
      component.setComponentID(metadata.getHeader().getId());
    } else if (UdtUtils.checkNull(metadata.getHeader().getId()) && !UdtUtils
        .checkNull(component.getComponentID())) //修改构件元数据时，需要为元数据的ID赋值
    {
      metadata.getHeader().setId(component.getComponentID());
    }
  }

  /**
   * 为元数据的Content属性赋值
   *
   * @param component 构件实体
   * @param metadata 元数据实体
   */
  private void EvaluateMetadataContent(GspComponent component, GspMetadata metadata) {
    metadata.setContent(component);
  }

  ///#region 根据元数据类型获取相应信息

  /**
   * 获取构件元数据拼接后缀名
   *
   * @param componentType 构件类型
   */
  private String GetCmpMetadataExtendSuffixByCompType(String componentType) {
//C# TO JAVA CONVERTER NOTE: The following 'switch' operated on a string member and was converted to Java 'if-else' logic:
//		switch (componentType)
//ORIGINAL LINE: case ComponentConstantElement.UDTValidComponent:
    if (componentType.equals(ComponentConstantElement.UDTValidComponent)) {
      return JavaCompCodeNames.UDTVldControllerName;
    }
//ORIGINAL LINE: case ComponentConstantElement.UDTDtmComponent:
    else if (componentType.equals(ComponentConstantElement.UDTDtmComponent)) {
      return JavaCompCodeNames.UDTDtmControllerName;
    } else {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_ENUM_NOTSUPPORT_0006, componentType);
    }
  }

  /**
   * 获取构件元数据扩展名
   *
   * @param componentType 构件类型
   */
  private String GetCmpMetadataExtendNameByCompType(String componentType) {
//C# TO JAVA CONVERTER NOTE: The following 'switch' operated on a string member and was converted to Java 'if-else' logic:
//		switch (componentType)
//ORIGINAL LINE: case ComponentConstantElement.UDTValidComponent:
    if (componentType.equals(ComponentConstantElement.UDTValidComponent)) {
      return JavaCompCodeNames.UDTValCmpExtendName;
    }
//ORIGINAL LINE: case ComponentConstantElement.UDTDtmComponent:
    else if (componentType.equals(ComponentConstantElement.UDTDtmComponent)) {
      return JavaCompCodeNames.UDTDtmCmpExtendName;
    } else {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_ENUM_NOTSUPPORT_0006, componentType);
    }
  }

  /**
   * 获取构件元数据类型
   *
   * @param componentType 构件类型
   */
  private String GetCmpMetadataTypeByCompType(String componentType) {
//C# TO JAVA CONVERTER NOTE: The following 'switch' operated on a string member and was converted to Java 'if-else' logic:
//		switch (componentType)
//ORIGINAL LINE: case ComponentConstantElement.UDTValidComponent:
    if (componentType.equals(ComponentConstantElement.UDTValidComponent)) {
      return JavaCompCodeNames.UDTValidComponent;
    }
//ORIGINAL LINE: case ComponentConstantElement.UDTDtmComponent:
    else if (componentType.equals(ComponentConstantElement.UDTDtmComponent)) {
      return JavaCompCodeNames.UDTDtmComponent;
    } else {
      throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_ENUM_NOTSUPPORT_0006, componentType);
    }
  }

  ///#endregion

  ///#endregion

  /**
   * 生成构件元数据
   *
   * @param metadata 元数据
   * @return 生成的构件元数据
   * <see cref="string"/>
   */
  private String GenerateGspMetadata(GspMetadata metadata) {
    MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
    metadata.setRelativePath(this.getMetadataPath());
    //创建元数据
    metadataService.createMetadata(this.getMetadataPath(), metadata);
    return metadata.getHeader().getCode();
  }

  private void UpdateComponentMetadata(GspMetadata metadata, String fullPath) {
    MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
    metadataService.saveMetadata(metadata, fullPath);
  }

  /**
   * 生成当前路径下唯一的元数据名称
   *
   * @param component 构件实体
   * @param path 生成的元数据存放路径
   * @return 唯一的要生成的元数据名称
   */
  private String GenerateComponentMetadataName(GspComponent component, String path) {
    // 构件元数据命名规则
    String metadataFileName = this.getBizEntityCode() + component.getComponentCode()
        + GetCmpMetadataExtendSuffixByCompType(component.getComponentType());
    // 若为新增元数据操作，则需要检查路径下是否有重名元数据；若为修改元数据操作，则无需操作
    if (this.getIsNewMetadata()) {
      String orgMetadataFileName = metadataFileName;
      String metadataFileNameWithSuffix =
          metadataFileName + GetCmpMetadataExtendNameByCompType(component.getComponentType());
      int index = 0;
      MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);

      while (metadataService.isMetadataExist(path, metadataFileNameWithSuffix)) {
        //（同一个Be元数据中，若有重名，则自动增加后缀）
        metadataFileName = orgMetadataFileName + ++index;
        metadataFileNameWithSuffix =
            metadataFileName + GetCmpMetadataExtendNameByCompType(component.getComponentType());
      }
      this.setComponentName(metadataFileName);
    }

    return metadataFileName;
  }
}